<template>
  <div
    class="node-status"
    v-if="nodeStatusObject?.[getNode().id]"
    :class="nodeStatusObject?.[getNode().id] + '-status'"
  >
    <img
      class="node-status-btn"
      :class="{ 'loading-image': nodeStatusObject[getNode().id] === NodeStatusEnumType.RUNNING }"
      :src="NodeStatusImg[nodeStatusObject[getNode().id]]"
      alt=""
    />
    <span>{{ NodeStatusNameEnumType[nodeStatusObject[getNode().id]] }}</span>
  </div>
  <div class="basic-node-top">
    <div class="node-top">
      <div class="node-top-info">
        <el-link
          :underline="false"
          class="link-btn"
          @click="nodeDta.isNodeFold = !nodeDta.isNodeFold"
        >
          <el-icon v-show="!nodeDta.isNodeFold"><ArrowDown /></el-icon>
          <el-icon v-show="nodeDta.isNodeFold"><ArrowRight /></el-icon>
        </el-link>
        <img :src="getNodeImg" />
        <div
          class="input-box"
          v-show="![nodesMap.START, NodeTypeEnum.ITERATION_BODY].includes(shape)"
          @mouseenter="nodeDta.isEdieIcon = true"
          @mouseleave="mouseleave"
        >
          <el-form :model="nodeDta" style="width: 100%" ref="RuleFormRef">
            <el-form-item
              style="margin-bottom: 0"
              prop="title"
              :rules="[
                {
                  required: true,
                  message: '请输入标题',
                  trigger: 'change'
                },
                { min: 1, max: 100, message: '标题长度不可超过100字符', trigger: 'change' },
                // {
                //   validator: ValidatorNodeTitle,
                //   title: nodeDta.title,
                //   getNode: getNode(),
                //   trigger: 'blur'
                // }
              ]"
            >
              <el-tooltip
                effect="dark"
                :content="nodeDta.title"
                :disabled="!nodeDta.title"
                placement="top-start"
              >
                <el-input
                  class="custom-input"
                  v-model.trim="nodeDta.title"
                  placeholder="请输入节点名称"
                  ref="CustomInputRef"
                  @focus="inputFocus"
                  @input="titleInput"
                />
              </el-tooltip>
            </el-form-item>
          </el-form>
          <img
            v-show="nodeDta.isEdieIcon"
            :src="editImg"
            class="edit-img"
            @click="imgClickInputFocus"
          />
        </div>
        <div
          class="node-title"
          v-show="[nodesMap.START, NodeTypeEnum.ITERATION_BODY].includes(shape)"
        >
          {{ nodeDta.title }}
        </div>
      </div>
      <div v-show="![NodeTypeEnum.START, NodeTypeEnum.ITERATION_BODY].includes(shape)">
        <el-dropdown
          popper-class="custom-dropdown"
          @command="command"
          @visible-change="visibleChange"
          :teleported="true"
        >
          <el-icon style="cursor: pointer; outline: none; color: rgba(42, 48, 58, 0.4)">
            <MoreFilled />
          </el-icon>
          <template #dropdown>
            <el-dropdown-menu>
              <el-dropdown-item command="copy">复制</el-dropdown-item>
              <el-dropdown-item command="delete" v-if="isShowDelete">删除</el-dropdown-item>
            </el-dropdown-menu>
          </template>
        </el-dropdown>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts" name="BasicNodeTop">
import { inject, onMounted, ref, computed, watch, nextTick } from 'vue';
import { storeToRefs } from 'pinia';

import editImg from '@/assets/images/app-management-images/edit.svg';
import { workFlowStoreCounter } from '@/store/work-flow';
import {GenerationNodeData} from '@/view/graph/methods/methods';
import {
  NodeFormType,
  NodeStatusEnumType,
  NodeStatusImg,
  NodeStatusNameEnumType,
  NodeTypeEnum
} from '@/view/graph/model/type';
import {NODES_MAP} from '@/view/graph/model/nodes';

const CustomInputRef = ref();
const RuleFormRef = ref();

const workFlowStore = workFlowStoreCounter();

const { nodeStatusObject, categoryGroupList, graph } = storeToRefs(workFlowStore);

const getNode = inject('getNode') as () => any;
const nodeForm = GenerationNodeData({ code: 'basic', name: '' }) as NodeFormType;
const nodeDta = ref<NodeFormType>({
  ...nodeForm
});
const shape = ref();
const nodesMap = NODES_MAP;
const isShowDelete = ref(true);

watch(
  nodeDta,
  newValue => {
    getNode().setData(
      {
        ...getNode().getData(),
        ...newValue,
        lastModify: new Date()
      },
      { overwrite: true }
    );
  },
  {
    deep: true
  }
);

onMounted(() => {
  nodeDta.value = getNode().getData();
  getNode().on('change:data', ({ current }: { current: NodeFormType }) => {
    nodeDta.value.isNodeFold = current.isNodeFold;
  });
  shape.value = getNode().shape;
});

function visibleChange(event: boolean) {
  if (event) {
    if (getNode().shape === NodeTypeEnum.END) {
      nextTick(() => {
        isShowDelete.value =
          graph.value?.getNodes()?.filter((item: any) => item.shape === nodesMap.END)?.length > 1;
      });
    }
    isShowDelete.value = true;
  }
}

/**
 * 节点图标
 */
const getNodeImg = computed(() => {
  const list = categoryGroupList.value.map(item => item.children).flat();
  return list.find(item => item.code === getNode().shape)?.img;
});

/**
 * input高亮
 */
function inputFocus() {
  CustomInputRef.value.ref.parentNode.style.boxShadow = '0 0 0 1px #dcdfe6';
  CustomInputRef.value.ref.parentNode.style.padding = '1px 11px';
}

/**
 * 点击编辑input高亮
 */
function imgClickInputFocus() {
  CustomInputRef.value.focus();
  inputFocus();
  nodeDta.value.isEdieIcon = false;
}

/**
 * 鼠标移除
 */
function mouseleave() {
  nodeDta.value.isEdieIcon = false;
  CustomInputRef.value.ref.parentNode.style.boxShadow = 'none';
  CustomInputRef.value.ref.parentNode.style.padding = '0';
  CustomInputRef.value.blur();
}

/**
 * 节点操作按钮事件
 * @param args
 */
function command(args: string) {
  const graph = getNode()._model.graph;
  if (args === 'copy') {
    if (getNode().shape === NodeTypeEnum.ITERATION) {
      const outNode = graph.getNeighbors(getNode(), { incoming: false, outgoing: true })[0];
      const edge = graph.getOutgoingEdges(getNode())[0];
      graph.copy([edge]);
      const pasteNode = graph.paste({
        offset: 30
      });
      if (outNode.children?.length > 0) {
        graph.copy(outNode.children);
        const childrenNode = graph.paste();
        const bodyNode = pasteNode.find((item: any) => item.shape === NodeTypeEnum.ITERATION_BODY);
        childrenNode?.forEach((item: any) => {
          bodyNode.addChild(item);
        });
      }
    } else {
      graph.copy([getNode()]);
      graph.paste({
        offset: 30
      });
    }
  } else if (args === 'delete') {
    if (getNode().shape === NodeTypeEnum.ITERATION) {
      const outNode = graph.getNeighbors(getNode(), { incoming: false, outgoing: true })?.[0];
      graph.removeNode(getNode());
      graph.removeNode(outNode);
    } else {
      graph.removeNode(getNode());
    }
  }
}

/**
 * form表单校验
 */
const submitForm = async (): Promise<boolean> => {
  if (!RuleFormRef.value) {
    return false;
  }
  return new Promise<boolean>(resolve => {
    RuleFormRef.value.validate((valid: boolean) => {
      resolve(valid);
    });
  });
};

function titleInput() {
  // NodeDataStore.changeNodeData(new Date());
}

defineExpose({
  submitForm
});
</script>

<style scoped lang="scss">
.basic-node-top {
  margin-bottom: 10px;
}
.node-title {
  margin-left: 6px;
  color: rgba(42, 48, 58, 0.8);
}
.succeeded-status {
  background: rgba(33, 200, 153, 0.05);
}
.failed-status {
  background: rgba(243, 80, 80, 0.05);
}
.running-status {
  background: rgba(54, 121, 235, 0.05);
}
.node-status {
  height: 40px;
  padding: 12px;
  margin: -13px -13px 12px -13px;
  color: #2a303a;
  font-size: 14px;
  font-weight: 500;
  display: flex;
}
.node-status-btn {
  margin-right: 8px;
}
.loading-image {
  animation: spin 2s linear infinite; /* 旋转动画 */
}

@keyframes spin {
  from {
    transform: rotate(0deg); /* 初始角度 */
  }
  to {
    transform: rotate(360deg); /* 旋转到 360 度 */
  }
}
</style>
